package com.gabejeff.engine;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;

import javax.swing.JFrame;

import com.gabejeff.exceptions.InvalidSceneException;

public abstract class Scene {
	
	/*
	 * Show FPS for debugging purposes
	 */
	private static boolean SHOW_FPS = true;
	
	private boolean done = false;
	private boolean overlay = false;
	protected BufferedImage underlying = null;
	protected Dimension dim = new Dimension();
	private BufferedImage buffer = null;
	private Graphics2D bufg2d = null;
    private static double fps = 0d;
    private static double tmpfps = 0d;
    private static long timeStart = 0l;
    private static JFrame frame;
	
	public abstract Scene getSubScene(int x, int y, int width, int height) throws InvalidSceneException;
	protected abstract BufferedImage render();
	public abstract void performMenuAction(boolean escape);
	public abstract void moveUp();
	public abstract void moveDown();
	public abstract void moveLeft();
	public abstract void moveRight();
	
	public static void setFrame(JFrame dest) {
		frame = dest;
	}
	
	public JFrame getFrame() {
		return this.frame;
	}
	
	public Scene getAction()
	{
		return null;
	}

	public boolean hasAction()
	{
		return false;
	}

	public  boolean isDone()
	{
		return this.done;
	}
	
	public void forceDone() 
	{
		this.done = true;
	}
	
	public void setUndone()
	{
		this.done = false;
	}

	public void setMenu( PlayerMenu m )
	{
		/* Do something here */
	}
	
	public void setOverlay(boolean overlay) 
	{
		this.overlay = overlay;
	}
	
	public boolean isOverlay() 
	{
		return this.overlay;
	}
	
	public void addUnderlying( BufferedImage underlying ) 
	{
		if (this.overlay) {
			this.underlying = underlying;
		}
	}
	
	public static void drawFPS( Graphics2D g ) {		
		g.setColor(Color.WHITE);
		g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
		fps++;
		
		// If at least one second has passed, let's display the framerate.
		if (System.currentTimeMillis() - timeStart >= 1000) {
			timeStart = System.currentTimeMillis();
			tmpfps = fps;
			fps = 0;
		}
		
		String sFPS = tmpfps + " FPS";
		g.setFont(new Font(g.getFont().getName(), Font.BOLD | Font.ITALIC, 16));
		g.drawString(sFPS, 5, g.getFontMetrics().getHeight());
	}
		
	public void paint( JFrame dest ) {
		/* Get the scene dimensions */
		int sceneWidth = dest.getWidth();
		int sceneHeight = dest.getHeight();
		
		Graphics2D g = (Graphics2D)dest.getGraphics();
		
		/* If the buffer has different dimensions than the scene, we need to resize it */
		if (buffer == null || 
		    buffer.getWidth() != sceneWidth || 
		    buffer.getHeight() != sceneHeight) {
			
			buffer = new BufferedImage(sceneWidth, 
					                   sceneHeight, 
					                   BufferedImage.TYPE_INT_ARGB);
		}
		
		bufg2d = buffer.createGraphics();
		
		/* Draw the scene to the buffer */
		bufg2d.setBackground(Color.WHITE);
		bufg2d.clearRect(0, 0, sceneWidth, sceneHeight);
		bufg2d.drawImage(render(), 0, 0, null);
		
		Insets insets = dest.getInsets();
		if (SHOW_FPS) {
			drawFPS(bufg2d);
		}
		/* Draw the buffer to the component */
		g.drawImage(buffer, insets.left, insets.top, null);
		
		/* Dispose the graphics components */
		bufg2d.dispose();
		g.dispose();
				
	}
	
	public BufferedImage getSnapshot() {
		/* Let's disable the FPS for the snapshot */
		boolean oldval = false;
		if (SHOW_FPS) {
			SHOW_FPS = false;
			oldval = true;
		}
		/* Get a snapshot of the buffer */
		BufferedImage buf = preBuffer();
		
		/* Re-enable the FPS if it was previously set */
		if (oldval) {
			SHOW_FPS = true;
		}
		return buf;
	}
	
	public BufferedImage preBuffer() {
		return render();
	}
	
}
